package com.example.demo.core.config;


import com.example.demo.core.handlerMapping.SpringHandlerMapping;
import com.example.demo.core.handlerMapping.interfaces.HandlerMapping;
import com.example.demo.core.service.SIPProcessorObserver;
import gov.nist.javax.sip.SipProviderImpl;
import gov.nist.javax.sip.SipStackImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import javax.sip.*;
import java.util.Properties;
import java.util.TooManyListenersException;

/**
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022/7/20
 */
@Configuration
@Slf4j
@EnableConfigurationProperties(value = SipConfig.class)
public class BeanConfig {

    private SipStackImpl sipStack;
    private SipFactory sipFactory;

    /**
     * 配置sip工厂bean
     *
     * @return
     */
    @Bean("sipFactory")
    SipFactory createSipFactory() {
        sipFactory = SipFactory.getInstance();
        sipFactory.setPathName("gov.nist");
        return sipFactory;
    }

    @Bean("sipStack")
    SipStack createSipStack(SipConfig sipConfig) throws PeerUnavailableException {
        Properties properties = new Properties();
        properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP");
        properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getIp());
        /**
         * 完整配置参考 gov.nist.javax.sip.SipStackImpl，需要下载源码
         * gov/nist/javax/sip/SipStackImpl.class
         */
        properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true");
        properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); // 接收所有notify请求，即使没有订阅
        properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); // 为_NULL _对话框传递_终止的_事件
        properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal"); // 会话清理策略
        properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "10");
        /**
         * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE =
         * 0; public static final int TRACE_MESSAGES = 16; public static final int
         * TRACE_EXCEPTION = 17; public static final int TRACE_DEBUG = 32;
         */
        properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "0");
        properties.setProperty("gov.nist.javax.sip.SERVER_LOG", "sip_server_log");
        properties.setProperty("gov.nist.javax.sip.DEBUG_LOG", "sip_debug_log");
        sipStack = (SipStackImpl) sipFactory.createSipStack(properties);
        return sipStack;
    }

    @Bean(name = "tcpSipProvider")
    SipProviderImpl startTcpListener(SipConfig sipConfig, SIPProcessorObserver sipProcessorObserver) throws ObjectInUseException, TooManyListenersException, TransportNotSupportedException, InvalidArgumentException {
        String ip = sipConfig.getIp();
        Integer port = sipConfig.getPort();
        SipProviderImpl tcpSipProvider = null;
        try {
            ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(ip, port, "TCP");
            tcpSipProvider = (SipProviderImpl) sipStack.createSipProvider(tcpListeningPoint);
            tcpSipProvider.setDialogErrorsAutomaticallyHandled();
            tcpSipProvider.addSipListener(sipProcessorObserver);
            log.info("[SIP SERVER] tcp://{}:{} 启动成功", ip, port);
        }catch (Exception e){
            log.error("[SIP SERVER] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确", ip, port);
        }
        return tcpSipProvider;

    }

    @Bean(name = "udpSipProvider")
    SipProviderImpl startUdpListener(SipConfig sipConfig, SIPProcessorObserver sipProcessorObserver)  {
        String ip = sipConfig.getIp();
        Integer port = sipConfig.getPort();
        SipProviderImpl udpSipProvider = null;
        try {
            ListeningPoint udpListeningPoint = sipStack.createListeningPoint(ip, port, "UDP");
            udpSipProvider = (SipProviderImpl) sipStack.createSipProvider(udpListeningPoint);
            udpSipProvider.addSipListener(sipProcessorObserver);
            log.info("[SIP SERVER] udp://{}:{} 启动成功", ip, port);
        }catch (Exception e){
            log.error("[SIP SERVER] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确", ip, port);
        }
        return udpSipProvider;
    }

    @Bean
    public HandlerMapping handlerMapping() {
        return new SpringHandlerMapping();
    }


}
